package com.db.stexchem.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.db.stexchem.message.ExecutionReport;

public class NotificationService {
  
  private final Logger                                                 logger = LoggerFactory
                                                                                  .getLogger(NotificationService.class);
  private final ConcurrentHashMap<String, Collection<ExecutionReport>> waitingNotifications;
  private final ConcurrentHashMap<String, ClientSession>               activeSessions;
  
  public NotificationService(
      ConcurrentHashMap<String, Collection<ExecutionReport>> waitingNotifications,
      ConcurrentHashMap<String, ClientSession> activeSessions) {
    this.waitingNotifications = waitingNotifications;
    this.activeSessions = activeSessions;
  }
  
  public synchronized void sendExecutionReports(final List<Match> matches) {
    Set<String> clients = new HashSet<>();
    for (Match match : matches) {
      String counterparty = match.getParty().getCounterparty();
      Collection<ExecutionReport> reports = waitingNotifications
          .get(counterparty);
      if (reports != null) {
        reports.add(match.getCounterparty());
      } else {
        reports = new ArrayList<>();
        reports.add(match.getCounterparty());
        waitingNotifications.put(counterparty, reports);
      }
      clients.add(counterparty);
      String party = match.getCounterparty().getCounterparty();
      reports = waitingNotifications.get(party);
      if (reports != null) {
        reports.add(match.getParty());
      } else {
        reports = new ArrayList<>();
        reports.add(match.getParty());
        waitingNotifications.put(party, reports);
      }
      clients.add(party);
    }
    for (String client : clients) {
      sendWaitingNotifications(client);
    }
  }
  
  public synchronized void sendWaitingNotifications(final String login) {
    try {
      Collection<ExecutionReport> reports = waitingNotifications.get(login);
      if (reports == null) {
        return;
      }
      logger.info("trying to send waiting notifications for client '{}' ...",
          login);
      ClientSession session = activeSessions.get(login);
      if (session == null) {
        logger.info("client '{}' is not connected", login);
        return;
      }
      
      Iterator<ExecutionReport> i = reports.iterator();
      while (i.hasNext()) {
        ExecutionReport executionReport = i.next();
        session.sendNotification(executionReport);
        logger.info(
            "execution report '{}' has been successfully sent to client '{}'",
            executionReport.toString(), login);
        i.remove();
      }
      waitingNotifications.remove(login);
    } catch (IOException e) { // don't care
    }
  }
  
}
